var mongodb = require('mongodb');
var deasync = require('deasync');
var mongo_server = require("./mongo_server");
var util = require("./utils/util");

var self = null;

module.exports = {
	config: null,
	servers: {},
	entity:{},
	dbs: {},
	init: function (config) {
		self = this;
		self.config = config;
		self.config.address.forEach((cfg) => {
			if (!cfg.name) cfg.name = "default";
			self.servers[cfg.name] = cfg;
		});
	},
	register_entity: function (context, service_name) {
		let entity_config = context.config;
		if (!entity_config || !entity_config.cluster) throw `mongo register entity fail ${service_name} not set configuration...`;
		
		let entity = context.exports;
		if (typeof entity !== "function") entity = context.module.exports;
		if (typeof entity !== "function") throw `mongo register entity fail entity[${service_name}] not exported entity...`;
		
		let server = self.servers[entity_config.cluster];
		if (!server) throw `mongo load entity ${entity_config.cluster} fail..`;
		
		let isReturn = false;
		
		let hash = entity_config.cluster + "." + entity_config.db;
		let init_collection = function () {
			let db = self.dbs[hash];
			db.collection(entity_config.col, function(err, collection) {
				if (err) throw `mongo register entity collection error:${err}`;
				else {
					let en_obj = {self: self, config: entity_config, entity: entity, mongo: {server: server, db: db, collection: collection}};
					en_obj.server = new mongo_server(en_obj);
					self.entity[service_name] = en_obj;
				}
				isReturn = true;
			});
		};
		if (self.dbs[hash]) init_collection();
		else{
			new mongodb.Db(entity_config.db, new mongodb.Server(server.address, server.port, server.cfg)).open((err, db) => {
				if (err) throw `mongo connect db ${entity_config.db} fail, err:" + ${err}`;
				self.dbs[hash] = db;
				init_collection();
			});
		}
		while(!isReturn) deasync.runLoopOnce();
	},
	get_entity: function (name) {
		return self.entity[name] && new self.entity[name].entity();
	},
	get_server: function (name) {
		return self.entity[name] && self.entity[name].server;
	}
};